home *** CD-ROM | disk | FTP | other *** search
- /* WinWave.c
- *
- * Windows Wave Sound Devicee
- *
- * $Id: winwave.c,v 1.8 1997/01/16 18:41:59 pekangas Exp $
- *
- * Copyright 1996,1997 Housemarque Inc.
- *
- * This file is part of the MIDAS Sound System, and may only be
- * used, modified and distributed under the terms of the MIDAS
- * Sound System license, LICENSE.TXT. By continuing to use,
- * modify or distribute this file you indicate that you have
- * read the license and understand and accept it fully.
- */
-
- #include <windows.h>
- #include <mmsystem.h>
- #include <stdio.h>
-
- #include "lang.h"
- #include "mtypes.h"
- #include "errors.h"
- #include "mglobals.h"
- #include "sdevice.h"
- #include "mmem.h"
- #include "dsm.h"
-
- RCSID(char const *winwave_rcsid = "$Id: winwave.c,v 1.8 1997/01/16 18:41:59 pekangas Exp $";)
-
- //#define DUMPBUFFER
-
- #define WINWVERSION 1.00
- #define WINWVERSTR "1.00"
-
-
- /* Maximum number of buffer blocks: (FIXME) */
- #define MAXBUFBLOCKS 32
-
- /* Number of bits of accuracy in mixing for 8-bit output: */
- #define MIX8BITS 12
-
-
-
-
- /* Sound Device information */
-
- /* Sound Card names: */
- static char *winwCardName = "Windows Wave output";
-
-
-
- /* Sound Device internal static variables */
- static unsigned mixRate, outputMode;
- static unsigned bufferLen, numBlocks, blockLen;
- static unsigned mixElemSize;
-
- static unsigned amplification;
- static unsigned updateMix; /* number of elements to mix between
- two updates */
- static unsigned mixLeft; /* number of elements to mix before
- next update */
-
-
- static HWAVEOUT waveHandle;
- static HANDLE blockHandles[MAXBUFBLOCKS];
- static uchar *blocks[MAXBUFBLOCKS];
- static HANDLE blockHeaderHandles[MAXBUFBLOCKS];
- static WAVEHDR *blockHeaders[MAXBUFBLOCKS];
- static int blockPrepared[MAXBUFBLOCKS];
-
- static unsigned blockNum; /* current mixing block number */
- static unsigned blockPos; /* mixing position inside block */
-
- static uchar *ppTable; /* post-processing table for 8-bit
- output */
-
- #ifdef DUMPBUFFER
- static FILE *buff;
- #endif
-
-
- /****************************************************************************\
- * enum winwFunctIDs
- * -----------------
- * Description: ID numbers for Windows Wave Sound Device functions
- \****************************************************************************/
-
- enum winwFunctIDs
- {
- ID_winwDetect = ID_winw,
- ID_winwInit,
- ID_winwClose,
- ID_winwGetMode,
- ID_winwOpenChannels,
- ID_winwSetAmplification,
- ID_winwGetAmplification,
- ID_winwSetUpdRate,
- ID_winwStartPlay,
- ID_winwPlay
- };
-
-
-
- /* Local prototypes: */
- int CALLING winwSetAmplification(unsigned _amplification);
- int CALLING winwGetAmplification(unsigned *_amplification);
- int CALLING winwSetUpdRate(unsigned updRate);
-
-
-
-
-
- /****************************************************************************\
- *
- * Function: static int winwError(MMRESULT error)
- *
- * Description: Converts a Windows multimedia system error code to MIDAS
- * error code
- *
- * Input: MMRESULT error Windows multimedia system error code
- *
- * Returns: MIDAS error code
- *
- \****************************************************************************/
-
- static int winwError(MMRESULT error)
- {
- switch ( error )
- {
- case MMSYSERR_NOERROR:
- return OK;
- case MMSYSERR_ERROR:
- return errUndefined;
- case MMSYSERR_BADDEVICEID:
- case MMSYSERR_INVALHANDLE:
- case MMSYSERR_NOTENABLED:
- return errInvalidDevice;
- case MMSYSERR_ALLOCATED:
- case MMSYSERR_HANDLEBUSY:
- return errDeviceBusy;
- case MMSYSERR_NODRIVER:
- return errDeviceNotAvailable;
- case MMSYSERR_NOMEM:
- return errOutOfMemory;
- case MMSYSERR_NOTSUPPORTED:
- return errUnsupported;
- case MMSYSERR_INVALFLAG:
- case MMSYSERR_INVALPARAM:
- return errInvalidArguments;
- case WAVERR_BADFORMAT:
- return errBadMode;
- case WAVERR_STILLPLAYING:
- return errDeviceBusy;
- case WAVERR_UNPREPARED:
- return errInvalidArguments;
- case WAVERR_SYNC:
- return errInvalidDevice;
- }
-
- return errUndefined;
- }
-
- /* Error code passing macros for multimedia system errors - similar to
- PASSERROR in errors.h: */
-
- #ifdef DEBUG
- #define PASSWINERR(error_, functID) { error = winwError(error_); \
- errAdd(winwError(error_), functID); return error; }
- #else
- #define PASSWINERR(error_, functID) return winwError(error_);
- #endif
-
-
-
-
- /****************************************************************************\
- *
- * Function: static unsigned CALLING (*postProc)(unsigned numElements,
- * uchar *bufStart, unsigned mixPos, unsigned *mixBuffer,
- * uchar *ppTable);
- *
- * Description: Pointer to the actual post-processing routine. Takes
- * DSM output elements from dsmMixBuffer and writes them to
- * output buffer at *bufStart in a format suitable for the Sound
- * Device.
- *
- * Input: unsigned numElements number of elements to process
- * (guaranteed to be even)
- * uchar *bufStart pointer to start of output buffer
- * unsigned mixPos mixing position in output buffer
- * unsigned *mixBuffer source mixing buffer
- * uchar *ppTable pointer to post-processing table
- *
- * Returns: New mixing position in output buffer. Can not fail.
- *
- \****************************************************************************/
-
- static unsigned CALLING (*postProc)(unsigned numElements, uchar *bufStart,
- unsigned mixPos, unsigned *mixBuffer, uchar *ppTable);
-
-
-
-
- /****************************************************************************\
- *
- * Function: unsigned pp16Mono();
- *
- * Description: 16-bit mono post-processing routine
- *
- \****************************************************************************/
-
- unsigned CALLING pp16Mono(unsigned numElements, uchar *bufStart,
- unsigned mixPos, unsigned *mixBuffer, uchar *ppTable);
-
-
-
-
- /****************************************************************************\
- *
- * Function: unsigned pp8Mono();
- *
- * Description: 8-bit mono post-processing routine
- *
- \****************************************************************************/
-
- unsigned CALLING pp8Mono(unsigned numElements, uchar *bufStart,
- unsigned mixPos, unsigned *mixBuffer, uchar *ppTable);
-
-
-
-
- /****************************************************************************\
- *
- * Function: unsigned pp16Stereo();
- *
- * Description: 16-bit stereo post-processing routine
- *
- \****************************************************************************/
-
- unsigned CALLING pp16Stereo(unsigned numElements, uchar *bufStart,
- unsigned mixPos, unsigned *mixBuffer, uchar *ppTable);
-
-
-
-
- /****************************************************************************\
- *
- * Function: unsigned pp8Stereo();
- *
- * Description: 8-bit stereo post-processing routine
- *
- \****************************************************************************/
-
- unsigned CALLING pp8Stereo(unsigned numElements, uchar *bufStart,
- unsigned mixPos, unsigned *mixBuffer, uchar *ppTable);
-
-
-
-
-
-
-
-
-
- /****************************************************************************\
- *
- * Function: int winwDetect(int *result)
- *
- * Description: Detects a Windows Wave Sound Device
- *
- * Input: int *result pointer to detection result
- *
- * Returns: MIDAS error code. Detection result (1 if detected, 0 if not)
- * is written to *result.
- *
- \****************************************************************************/
-
- int CALLING winwDetect(int *result)
- {
- /* Check that we have at least one wave output device: */
- if ( waveOutGetNumDevs() < 1 )
- *result = 0;
- else
- *result = 1;
-
- return OK;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: int winwInit(unsigned mixRate, unsigned mode)
- *
- * Description: Initializes Windows Wave Sound Device
- *
- * Input: unsigned mixRate mixing rate in Hz
- * unsigned mode output mode
- *
- * Returns: MIDAS error code
- *
- \****************************************************************************/
-
- int CALLING winwInit(unsigned _mixRate, unsigned mode)
- {
- unsigned i;
- MMRESULT mmError;
- int error;
- WAVEHDR *header;
- WAVEFORMATEX format;
- int mixMode;
-
- mixRate = _mixRate;
-
- /* Determine the actual output mode: */
- if ( mode & sdMono )
- outputMode = sdMono;
- else
- outputMode = sdStereo;
- if ( mode & sd8bit )
- outputMode |= sd8bit;
- else
- outputMode |= sd16bit;
-
- /* Calculate one mixing element size: */
- if ( outputMode & sd16bit )
- mixElemSize = 2;
- else
- mixElemSize = 1;
- if ( outputMode & sdStereo )
- mixElemSize <<= 1;
-
- /* Limit number of blocks to MAXBUFBLOCKS: */
- numBlocks = mBufferBlocks;
- if ( numBlocks > MAXBUFBLOCKS )
- numBlocks = MAXBUFBLOCKS;
-
- /* Calculate required buffer block length: (must be a multiple of
- 16 bytes) */
- blockLen = mixRate * mixElemSize * mBufferLength / 1000 / numBlocks;
- blockLen = (blockLen + 15) & (~15);
-
- bufferLen = numBlocks * blockLen;
-
- blockNum = blockPos = 0;
-
- /* Set up wave output format structure: */
- format.wFormatTag = WAVE_FORMAT_PCM;
- if ( outputMode & sdStereo )
- format.nChannels = 2;
- else
- format.nChannels = 1;
- format.nSamplesPerSec = mixRate;
- format.nAvgBytesPerSec = mixElemSize * mixRate;
- format.nBlockAlign = mixElemSize;
- if ( outputMode & sd16bit )
- format.wBitsPerSample = 16;
- else
- format.wBitsPerSample = 8;
- format.cbSize = 0;
-
- /* Open wave output device using the format just set up: */
- if ( (mmError = waveOutOpen(&waveHandle, WAVE_MAPPER, &format, 0, 0, 0))
- != 0 )
- PASSWINERR(mmError, ID_winwInit);
-
- /* Allocate and lock memory for all mixing blocks: */
- for ( i = 0; i < numBlocks; i++ )
- {
- /* Allocate global memory for mixing block: */
- if ( (blockHandles[i] = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
- blockLen)) == NULL )
- {
- ERROR(errOutOfMemory, ID_winwInit);
- return errOutOfMemory;
- }
- /* printf("Block %i handle %08X\n", i, blockHandles[i]); */
-
- /* Lock mixing block memory: */
- if ( (blocks[i] = GlobalLock(blockHandles[i])) == NULL )
- {
- ERROR(errUnableToLock, ID_winwInit);
- return errUnableToLock;
- }
- }
-
- /* Allocate and lock memory for all mixing block headers: */
- for ( i = 0; i < numBlocks; i++ )
- {
- /* Allocate global memory for mixing block: */
- if ( (blockHeaderHandles[i] = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
- sizeof(WAVEHDR))) == NULL )
- {
- ERROR(errOutOfMemory, ID_winwInit);
- return errOutOfMemory;
- }
-
- /* Lock mixing block memory: */
- if ( (header = blockHeaders[i] = GlobalLock(blockHeaderHandles[i]))
- == NULL )
- {
- ERROR(errUnableToLock, ID_winwInit);
- return errUnableToLock;
- }
-
- /* Reset wave header fields: */
- header->lpData = blocks[i];
- header->dwBufferLength = blockLen;
- header->dwFlags = WHDR_DONE; /* mark the block is done */
- header->dwLoops = 0;
-
- /* Block header is not prepared: */
- blockPrepared[i] = 0;
- }
-
- /* Allocate memory for post-processing table if necessary: */
- if ( outputMode & sd8bit )
- {
- /* Allocate memory for 8-bit output mode post-processing table: */
- if ( (error = memAlloc((1 << MIX8BITS), &ppTable)) != OK )
- PASSERROR(ID_winwInit);
- }
- else
- ppTable = NULL;
-
- /* Check correct mixing mode: */
- if ( outputMode & sdStereo )
- mixMode = dsmMixStereo;
- else
- mixMode = dsmMixMono;
-
- /* Initialize Digital Sound Mixer: */
- if ( outputMode & sd16bit )
- {
- if ( (error = dsmInit(mixRate, mixMode, 16)) != OK )
- PASSERROR(ID_winwInit)
- }
- else
- {
- if ( (error = dsmInit(mixRate, mixMode, MIX8BITS)) != OK )
- PASSERROR(ID_winwInit)
- }
-
- /* Set update rate to 50Hz: */
- if ( (error = winwSetUpdRate(5000)) != OK )
- PASSERROR(ID_winwInit)
-
- /* Point postProc() to correct post-processing routine: */
- switch ( outputMode )
- {
- case (sd16bit | sdMono):
- postProc = &pp16Mono;
- break;
-
- case (sd8bit | sdMono):
- postProc = &pp8Mono;
- break;
-
- case (sd16bit | sdStereo):
- postProc = &pp16Stereo;
- break;
-
- case (sd8bit | sdStereo):
- postProc = &pp8Stereo;
- break;
-
- default:
- ERROR(errInvalidArguments, ID_winwInit);
- return errInvalidArguments;
- }
-
- amplification = 64;
-
- #ifdef DUMPBUFFER
- buff = fopen("buffer.raw", "wb");
- #endif
-
- return OK;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: winwClose(void)
- *
- * Description: Uninitializes Windows Wave Sound Device
- *
- * Returns: MIDAS error code
- *
- \****************************************************************************/
-
- int CALLING winwClose(void)
- {
- int error;
- MMRESULT mmError;
- unsigned i;
- int allDone;
- DWORD lasterror;
-
- #ifdef DUMPBUFFER
- fclose(buff);
- #endif
-
- /* Uninitialize Digital Sound Mixer: */
- if ( (error = dsmClose()) != OK )
- PASSERROR(ID_winwClose)
-
- /* Deallocate post-processing table if necessary: */
- if ( outputMode & sd8bit )
- {
- if ( (error = memFree(ppTable)) != OK )
- PASSERROR(ID_winwClose);
- }
-
- /* Reset wave output device, stop playback, and mark all blocks done: */
- if ( (mmError = waveOutReset(waveHandle)) != 0 )
- PASSWINERR(mmError, ID_winwClose);
-
- /* Make sure all blocks are indeed done: */
- while ( 1 )
- {
- allDone = 1;
- for ( i = 0; i < numBlocks; i++ )
- {
- if ( (blockHeaders[i]->dwFlags & WHDR_DONE) == 0 )
- allDone = 0;
- }
- if ( allDone )
- break;
- Sleep(20);
- }
-
- /* Unprepare all mixing blocks: */
- for ( i = 0; i < numBlocks; i++ )
- {
- if ( blockPrepared[i] )
- {
- if ( (mmError = waveOutUnprepareHeader(waveHandle, blockHeaders[i],
- sizeof(WAVEHDR))) != 0 )
- PASSWINERR(mmError, ID_winwClose);
- }
- }
-
- /* Close wave output device: */
- if ( (mmError = waveOutClose(waveHandle)) != 0 )
- PASSWINERR(mmError, ID_winwClose);
-
- /* Unlock and deallocate all mixing blocks: */
- for ( i = 0; i < numBlocks; i++ )
- {
- /* printf("Unlock block %i\n", i); */
- /* Unlock the mixing block handle: */
- if ( (!GlobalUnlock(blockHandles[i])) && ((lasterror = GetLastError())
- != NO_ERROR) )
- {
- /*
- printf("GetLastError(): %u, Handle: %08X\n", lasterror,
- blockHandles[i]);
- */
- ERROR(errHeapCorrupted, ID_winwClose);
- return errHeapCorrupted;
- }
-
- /* printf("Free block %i\n", i); */
- /* Deallocate the mixing block: */
- if ( GlobalFree(blockHandles[i]) != NULL )
- {
- ERROR(errHeapCorrupted, ID_winwClose);
- return errHeapCorrupted;
- }
- }
-
- /* Unlock and deallocate all mixing block headers: */
- for ( i = 0; i < numBlocks; i++ )
- {
- /* printf("Unlock header %i\n", i); */
- /* Unlock the mixing block header handle: */
- if ( (!GlobalUnlock(blockHeaderHandles[i])) && (
- GetLastError() != NO_ERROR) )
- {
- ERROR(errHeapCorrupted, ID_winwClose);
- return errHeapCorrupted;
- }
-
- /* printf("Free header %i\n", i); */
- /* Deallocate the mixing block: */
- if ( GlobalFree(blockHeaderHandles[i]) != NULL )
- {
- ERROR(errHeapCorrupted, ID_winwClose);
- return errHeapCorrupted;
- }
- }
-
- return OK;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: int winwGetMode(unsigned *mode)
- *
- * Description: Reads the current output mode
- *
- * Input: unsigned *mode pointer to output mode
- *
- * Returns: MIDAS error code. Output mode is written to *mode.
- *
- \****************************************************************************/
-
- int CALLING winwGetMode(unsigned *mode)
- {
- *mode = outputMode;
-
- return OK;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: int winwOpenChannels(unsigned channels)
- *
- * Description: Opens sound channels for output. Prepares post-processing
- * tables, takes care of default amplification and finally opens
- * DSM channels. Channels can be closed by simply calling
- * dsmCloseChannels().
- *
- * Input: unsigned channels number of channels to open
- *
- * Returns: MIDAS error code
- *
- \****************************************************************************/
-
- int CALLING winwOpenChannels(unsigned channels)
- {
- int error;
-
- /* Open DSM channels: */
- if ( (error = dsmOpenChannels(channels)) != OK )
- PASSERROR(ID_winwOpenChannels)
-
- /* Take care of default amplification and calculate new post-processing
- table if necessary: */
- /*
- if ( outputMode & sd8bit )
- {
- */
- if ( channels < 5 )
- winwSetAmplification(64);
- else
- winwSetAmplification(14*channels);
- /*
- }
- */
-
- return OK;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void CalcPP8Table(void)
- *
- * Description: Calculates a new 8-bit output post-processing table using
- * current amplification level
- *
- \****************************************************************************/
-
- static void CalcPP8Table(void)
- {
- uchar *tbl;
- int val;
- long temp;
-
- tbl = ppTable; /* tbl points to current table pos */
-
- /* Calculate post-processing table for all possible DSM values:
- (table must be used with unsigned numbers - add (1 << MIX8BITS)/2 to
- DSM output values first) */
- for ( val = -(1 << MIX8BITS)/2; val < (1 << MIX8BITS)/2; val++ )
- {
- /* Calculate 8-bit unsigned output value corresponding to the
- current DSM output value (val), taking amplification into
- account: */
- temp = 128 + ((((long) amplification) * ((long) val) / 64L) >>
- (MIX8BITS-8));
-
- /* Clip the value to fit between 0 and 255 inclusive: */
- if ( temp < 0 )
- temp = 0;
- if ( temp > 255 )
- temp = 255;
-
- /* Write the value to the post-processing table: */
- *(tbl++) = (uchar) temp;
- }
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: int winwSetAmplification(unsigned amplification)
- *
- * Description: Sets the amplification level. Calculates new post-processing
- * tables and calls dsmSetAmplification() as necessary.
- *
- * Input: unsigned amplification amplification value
- *
- * Returns: MIDAS error code
- *
- \****************************************************************************/
-
- int CALLING winwSetAmplification(unsigned _amplification)
- {
- int error;
-
- amplification = _amplification;
-
- if ( outputMode & sd8bit )
- {
- /* 8-bit output mode - do not set amplification level using DSM,
- but calculate a new post-processing table instead: */
- CalcPP8Table();
- }
- else
- {
- /* Set amplification level to DSM: */
- if ( (error = dsmSetAmplification(amplification)) != OK )
- PASSERROR(ID_winwSetAmplification)
- }
-
- return OK;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: int winwGetAmplification(unsigned *amplification);
- *
- * Description: Reads the current amplification level. (DSM doesn't
- * necessarily know the actual amplification level if
- * post-processing takes care of amplification)
- *
- * Input: unsigned *amplification pointer to amplification level
- *
- * Returns: MIDAS error code. Amplification level is written to
- * *amplification.
- *
- \****************************************************************************/
-
- int CALLING winwGetAmplification(unsigned *_amplification)
- {
- *_amplification = amplification;
-
- return OK;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: int winwSetUpdRate(unsigned updRate);
- *
- * Description: Sets the channel value update rate (depends on song tempo)
- *
- * Input: unsigned updRate update rate in 100*Hz (eg. 50Hz
- * becomes 5000).
- *
- * Returns: MIDAS error code
- *
- \****************************************************************************/
-
- int CALLING winwSetUpdRate(unsigned updRate)
- {
- /* Calculate number of elements to mix between two updates: (even) */
- mixLeft = updateMix = ((unsigned) ((100L * (ulong) mixRate) /
- ((ulong) updRate)) + 1) & 0xFFFFFFFE;
-
- return OK;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: int winwStartPlay(void)
- *
- * Description: Prepares for playing - doesn't actually do anything here...
- *
- * Returns: MIDAS error code
- *
- \****************************************************************************/
-
- int CALLING winwStartPlay(void)
- {
- return OK;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: int winwPlay(int *callMP);
- *
- * Description: Plays the sound - mixes the correct amount of data with DSM
- * and copies it to wave output buffer with post-processing.
- * Also takes care of sending fully mixed blocks to the wave
- * output device.
- *
- * Input: int *callMP pointer to music player calling flag
- *
- * Returns: MIDAS error code. If enough data was mixed for one updating
- * round and music player should be called, 1 is written to
- * *callMP, otherwise 0 is written there. Note that if music
- * player can be called, winwPlay() should be called again
- * with a new check for music playing to ensure the mixing buffer
- * gets filled with new data.
- *
- \****************************************************************************/
-
- int CALLING winwPlay(int *callMP)
- {
- int error;
- MMRESULT mmError;
- unsigned blockLeft, numElems;
- unsigned dsmBufSize;
- unsigned oldPos;
-
- /* Calculate DSM mixing buffer size in elements: (FIXME) */
- dsmBufSize = dsmMixBufferSize;
- #ifdef __32__
- dsmBufSize >>= 2;
- #else
- dsmBufSize >>= 1;
- #endif
- if ( outputMode & sdStereo )
- dsmBufSize >>= 1;
-
- /* Repeat while we have unused blocks left: */
-
- while ( blockHeaders[blockNum]->dwFlags & WHDR_DONE )
- {
- /* Check if the block is prepared - if so, unprepare it: */
- if ( blockPrepared[blockNum] )
- {
- if ( (mmError = waveOutUnprepareHeader(waveHandle,
- blockHeaders[blockNum], sizeof(WAVEHDR))) != 0 )
- PASSWINERR(mmError, ID_winwPlay);
- blockPrepared[blockNum] = 0;
- }
-
- /* Calculate number of bytes of block left: */
- blockLeft = blockLen - blockPos;
-
- /* Calculate number of mixing elements left: */
- numElems = blockLeft / mixElemSize;
-
- /* Check that we won't mix more data than there is to the next
- update: */
- if ( numElems > mixLeft )
- numElems = mixLeft;
-
- /* Check that we won't mix more data than fits to DSM mixing
- buffer: */
- if ( numElems > dsmBufSize )
- numElems = dsmBufSize;
-
- /* Decrease number of elements before next update: */
- mixLeft -= numElems;
-
- /* Mix the data to DSM mixing buffer: */
- if ( (error = dsmMixData(numElems)) != OK )
- PASSERROR(ID_winwPlay)
-
- /* Write the mixed data to output buffer: */
- oldPos = blockPos;
- blockPos = postProc(numElems, blocks[blockNum], blockPos,
- dsmMixBuffer, ppTable);
-
- #ifdef DUMPBUFFER
- fwrite(&blocks[blockNum][oldPos], numElems * mixElemSize, 1, buff);
- #endif
-
- /* Check if the block is full - if so, write it to the wave output
- device and move to the next one: */
- if ( blockPos >= blockLen )
- {
- blockHeaders[blockNum]->dwFlags = 0;
- /* Reset wave header fields: */
- blockHeaders[blockNum]->lpData = blocks[blockNum];
- blockHeaders[blockNum]->dwBufferLength = blockLen;
- blockHeaders[blockNum]->dwFlags = 0;
- blockHeaders[blockNum]->dwLoops = 0;
-
- /* Prepare block header: */
- if ( (mmError = waveOutPrepareHeader(waveHandle,
- blockHeaders[blockNum], sizeof(WAVEHDR))) != 0 )
- PASSWINERR(mmError, ID_winwPlay);
- blockPrepared[blockNum] = 1;
-
- if ( (mmError = waveOutWrite(waveHandle, blockHeaders[blockNum],
- sizeof(WAVEHDR))) != 0 )
- PASSWINERR(mmError, ID_winwPlay);
-
- //blockNum = (blockNum++) % numBlocks;
- blockPos = 0;
- blockNum++;
- if ( blockNum >= numBlocks )
- blockNum = 0;
- }
-
- /* Check if the music player should be called: */
- if ( mixLeft == 0 )
- {
- mixLeft = updateMix;
- *callMP = 1;
- return OK;
- }
- }
-
- /* No more data fits to the mixing blocks - just return without
- update: */
- *callMP = 0;
-
- return OK;
- }
-
-
-
-
-
-
- /* WinWave Sound Device structure: */
-
- SoundDevice WinWave = {
- 0, /* tempoPoll = 0 */
- sdUseMixRate | sdUseOutputMode | sdUseDSM, /* configBits */
- 0, /* port */
- 0, /* IRQ */
- 0, /* DMA */
- 1, /* cardType */
- 1, /* numCardTypes */
- sdMono | sdStereo | sd8bit | sd16bit, /* modes */
-
- "Windows Wave Sound Device " WINWVERSTR, /* name */
- &winwCardName, /* cardNames */
- 0, /* numPortAddresses */
- NULL, /* portAddresses */
-
- &winwDetect,
- &winwInit,
- &winwClose,
- &dsmGetMixRate,
- &winwGetMode,
- &winwOpenChannels,
- &dsmCloseChannels,
- &dsmClearChannels,
- &dsmMute,
- &dsmPause,
- &dsmSetMasterVolume,
- &dsmGetMasterVolume,
- &winwSetAmplification,
- &winwGetAmplification,
- &dsmPlaySound,
- &dsmReleaseSound,
- &dsmStopSound,
- &dsmSetRate,
- &dsmGetRate,
- &dsmSetVolume,
- &dsmGetVolume,
- &dsmSetSample,
- &dsmGetSample,
- &dsmSetPosition,
- &dsmGetPosition,
- &dsmGetDirection,
- &dsmSetPanning,
- &dsmGetPanning,
- &dsmMuteChannel,
- &dsmAddSample,
- &dsmRemoveSample,
- &winwSetUpdRate,
- &winwStartPlay,
- &winwPlay
- #ifdef SUPPORTSTREAMS
- ,
- &dsmStartStream,
- &dsmStopStream,
- &dsmSetLoopCallback,
- &dsmSetStreamWritePosition
- #endif
- };
-
-
- /*
- * $Log: winwave.c,v $
- * Revision 1.8 1997/01/16 18:41:59 pekangas
- * Changed copyright messages to Housemarque
- *
- * Revision 1.7 1997/01/16 18:28:40 pekangas
- * Added pointer to dsmSetStreamWritePosition
- *
- * Revision 1.6 1996/07/29 19:33:10 pekangas
- * Added a proper detection function
- *
- * Revision 1.5 1996/07/13 19:56:40 pekangas
- * Eliminated Visual C warnings
- *
- * Revision 1.4 1996/07/08 19:40:32 pekangas
- * Fixed winwClose() calling convention
- *
- * Revision 1.3 1996/05/26 20:57:00 pekangas
- * Added StartStream and EndStream to WinWave Sound Device structure
- *
- * Revision 1.2 1996/05/25 09:32:47 pekangas
- * Changed to use mBufferLength and mBufferBlocks
- *
- * Revision 1.1 1996/05/22 20:49:33 pekangas
- * Initial revision
- *
- */